﻿// -------------------------------------------------------------------------
//    @FileName         :    NFPackageModule.cpp
//    @Author           :    gaoyi
//    @Date             :    2024/12/12
//    @Email            :    445267987@qq.com
//    @Module           :    NFPackageModule
//
// -------------------------------------------------------------------------

// --- 文件总结 ---------------------------------------------------------------
// 本文件实现 NFPackageModule 类的功能：
// 
// 【模块初始化】
// - Awake：注册所有客户端和服务器消息处理函数
// 
// 【客户端消息处理】
// - OnHandleClientMessage：分发客户端消息到对应的处理函数
// - ProcessArrangeBagReq：处理整理背包请求
// - ProcessBuyGridReq：处理购买格子请求
// - ProcessUseItemReq：处理使用物品请求
// - ProcessBoxSelectReq：处理宝箱选择请求
// - ProcessSaveToStorageReq：处理保存到仓库请求
// - ProcessPickFromStorageReq：处理从仓库取出请求
// - ProcessItemExchangeReq：处理物品兑换请求
// - ProcessThrowawayReq：处理丢弃物品请求
// - ProcessMoneyExchangeReq：处理金钱兑换请求
// - ProcessDecomposeReq：处理分解物品请求
// 
// 【服务器消息处理】
// - OnHandleServerMessage：分发服务器消息到对应的处理函数
// - ProcessOnlineArrangeBag：处理在线整理背包
// - ProcessOnlineBuyBagGrid：处理在线购买背包格子
// - ProcessStorageItemChange：处理仓库物品变更
// 
// 【辅助功能】
// - UseItemSuccess：使用物品成功回调
// ---------------------------------------------------------------------------

#include "NFPackageModule.h"

#include <NFPackagePart.h>
#include <NFPacketSendUtil.h>
#include <NFPlayer.h>
#include <NFPlayerUtil.h>
#include <NFSession.h>

#include "NFLogicCommon/BagPage/NFBagPageGrid.h"
#include "NFLogicCommon/BagPage/NFBagPageOp.h"
#include "NFBagPageOpMgr.h"
#include "NFItemUseFactory.h"
#include "NFServicePackage.h"
#include "NFTransOpStoreageBag.h"
#include "DescStore/BagDesc.h"

#include "proto_cs_bag.nanopb.h"
#include "proto_cs_cmd.nanopb.h"
#include "proto_svr_bag.nanopb.h"
#include "proto_svr_common.nanopb.h"

NFPackageModule::NFPackageModule(NFIPluginManager* p) : NFLogicDynamicModule(p)
{
}

NFPackageModule::~NFPackageModule()
{
}

int NFPackageModule::Awake()
{
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_BUY_BAG_GRID_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_ARRANGE_BAG_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_ITEM_USE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_BOX_SELECT_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_BUY_STORAGE_PAGE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_STORAGE_SAVE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_STORAGE_PICK_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_ITEM_EXCHANGE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_STORAGE_THROWAWAY_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_MONEY_EXCHANGE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_ITEM_DECOMPOS_REQ);

    ///////////////////////////online bag//////////////////////////////////
    RegisterServerMessage(NF_ST_LOGIC_SERVER, proto_ff::E_SS_ONLINE_ROLE_ARRANGE_BAG);
    RegisterServerMessage(NF_ST_LOGIC_SERVER, proto_ff::E_SS_ONLINE_ROLE_BUY_BAG_GRID);
    RegisterServerMessage(NF_ST_LOGIC_SERVER, proto_ff::E_SS_STORAGE_ITEM_CHANGE);

    return 0;
}

int NFPackageModule::OnHandleClientMessage(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    if (!m_pObjPluginManager->IsInited(NF_ST_LOGIC_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server is Stopping, drop client msg:{}", packet.ToString());
        return proto_ff::ERR_CODE_SERVER_IS_STOPPING;
    }

    int iRetCode = 0;
    switch (packet.nMsgId)
    {
        case proto_ff::E_CS_ARRANGE_BAG_REQ:
        {
            iRetCode = ProcessArrangeBagReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_BUY_BAG_GRID_REQ:
        {
            iRetCode = ProcessBuyGridReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_ITEM_USE_REQ:
        {
            iRetCode = ProcessUseItemReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_BOX_SELECT_REQ:
        {
            iRetCode = ProcessBoxSelectReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_STORAGE_SAVE_REQ:
        {
            iRetCode = ProcessSaveToStorageReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_STORAGE_PICK_REQ:
        {
            iRetCode = ProcessPickFromStorageReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_ITEM_EXCHANGE_REQ:
        {
            iRetCode = ProcessItemExchangeReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_STORAGE_THROWAWAY_REQ:
        {
            iRetCode = ProcessThrowawayReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_MONEY_EXCHANGE_REQ:
        {
            iRetCode = ProcessMoneyExchangeReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_ITEM_DECOMPOS_REQ:
        {
            iRetCode = ProcessDecomposeReq(packet, pSession, req);
            break;
        }
        default:
        {
            iRetCode = -1;
            NFLogError(NF_LOG_DEFAULT, 0, "not handle msg:{}", packet.nMsgId);
        }
    }

    return iRetCode;
}

int NFPackageModule::OnHandleServerMessage(uint64_t unLinkId, NFDataPackage& packet)
{
    if (!m_pObjPluginManager->IsInited(NF_ST_LOGIC_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server is Stopping, drop client msg:{}", packet.ToString());
        return proto_ff::ERR_CODE_SERVER_IS_STOPPING;
    }

    int iRetCode = 0;
    switch (packet.nMsgId)
    {
        case proto_ff::E_SS_ONLINE_ROLE_ARRANGE_BAG:
        {
            iRetCode = ProcessOnlineArrangeBag(unLinkId, packet);
            break;
        }
        case proto_ff::E_SS_ONLINE_ROLE_BUY_BAG_GRID:
        {
            iRetCode = ProcessOnlineBuyBagGrid(unLinkId, packet);
            break;
        }
        case proto_ff::E_SS_STORAGE_ITEM_CHANGE:
        {
            iRetCode = ProcessStorageItemChange(unLinkId, packet);
            break;
        }
        default:
        {
            iRetCode = -1;
            NFLogError(NF_LOG_DEFAULT, 0, "not handle msg:{}", packet.nMsgId);
        }
    }
    return iRetCode;
}

int NFPackageModule::ProcessArrangeBagReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);
    if (req.page_type() == proto_ff::EN_BPT_STORAGE)
    {
        pPlayer->SendMsgToOnlineServer(E_SS_ONLINE_ROLE_ARRANGE_BAG, req);
    }
    else
    {
        proto_ff::Proto_CSRsp respond;

        NFPackagePart* pPackage = pPlayer->GetPart<NFPackagePart>(PART_PACKAGE);
        CHECK_NULL(pPlayer->GetRoleID(), pPackage);

        auto pPage = pPackage->Arrage(req.page_type());
        CHECK_NULL(pPlayer->GetRoleID(), pPage);

        pPage->MakeGridCSData(respond.mutable_arrange_rsp()->mutable_grid_list());
        respond.mutable_arrange_rsp()->set_storage_page(req.page_type());
        return NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ARRANGE_BAG_RSP, &respond);
    }
    return 0;
}

int NFPackageModule::ProcessOnlineArrangeBag(uint64_t unLinkId, NFDataPackage& packet)
{
    proto_ff::Proto_OnlineToLogicArrageBagRsp xData;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, xData);

    uint64_t ullRoleID = packet.nModKey;
    int iRetCode = 0;
    NFPlayer* pPlayer = NFPlayerUtil::GetPlayerByRoleID(ullRoleID);
    CHECK_NULL(ullRoleID, pPlayer);

    if (xData.result() != 0)
    {
        NFPacketSendUtil::SendErrToClient(pPlayer, proto_ff::E_CS_ARRANGE_BAG_RSP, xData.result());
    }
    else
    {
        proto_ff::Proto_CSRsp respond;
        *respond.mutable_arrange_rsp() = xData.rsp();
        NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ARRANGE_BAG_RSP, &respond);
    }
    return 0;
}

int NFPackageModule::ProcessBuyGridReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSBuyBagGridInfo& msg = req.buy_bag_grid_req();
    auto pBagDesc = BagDesc::Instance()->GetDescByTypeTimes(msg.page(), msg.times());
    CHECK_NULL_WF(pPlayer->GetRoleID(), pBagDesc, "page:{} times:{}", msg.page(), msg.times());

    int iOldCapacity = 0;
    int iNewCapacity = 0;
    if (msg.page() == proto_ff::EN_BPT_STORAGE)
    {
        NFTransOpStoreageBag* pTrans = NFTransOpStoreageBag::CreateTrans();
        pTrans->Init(pPlayer, proto_ff::E_CS_BUY_BAG_GRID_REQ, packet.nMsgSeq);
        iRetCode = pTrans->ProcessCSMsgReq(&msg);
        CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "ProcessCSMsgReq failed");
        return 0;
    }
    else
    {
        NFBagPageOpMgr opMgr(pPlayer, proto_ff::EN_ICR_BUY_BAG_GRID, true);
        iRetCode = opMgr.DelItems(pBagDesc->use_item_id, pBagDesc->use_item_num);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "page:{} times:{} use_item_id:{} use_item_num:{}", msg.page(), msg.times(), pBagDesc->use_item_id, pBagDesc->use_item_num);

        NFPackagePart* pPackage = pPlayer->GetPart<NFPackagePart>(PART_PACKAGE);
        CHECK_NULL(pPlayer->GetRoleID(), pPackage);

        NFBagPage* pPage = pPackage->GetPageByType(msg.page());
        CHECK_NULL_WF(pPlayer->GetRoleID(), pPage, "page index error:{}", msg.page());

        if (pBagDesc->times != pPage->GetOpenGridTimes() + 1)
        {
            LOG_ERR(pPlayer->GetRoleID(), -1, "param of times error:{} {}", pBagDesc->times, pPage->GetOpenGridTimes());
            return proto_ff::ERR_CODE_INVALID_REQ_PARAM;
        }

        iRetCode = pPage->AddCapacity(pBagDesc->grids, &iOldCapacity, &iNewCapacity);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "bag:{} AddCapacity:{} failed", msg.page(), pBagDesc->grids);

        iRetCode = opMgr.Commit(true);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");

        proto_ff::Proto_CSRsp respond;
        proto_ff::Proto_CSBuyBagGridInfo* presult = respond.mutable_buy_bag_grid_rsp();
        presult->set_times(msg.times());
        presult->set_page(msg.page());
        presult->set_total_grid(iNewCapacity);
        return NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_BUY_BAG_GRID_RSP, &respond);
    }

    return 0;
}

int NFPackageModule::ProcessOnlineBuyBagGrid(uint64_t unLinkId, NFDataPackage& packet)
{
    proto_ff::Proto_OnlineToLogicBuyBagGridRsp xData;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, xData);

    uint64_t ullRoleID = packet.nModKey;
    NFPlayer* pPlayer = NFPlayerUtil::GetPlayerByRoleID(ullRoleID);
    CHECK_NULL(ullRoleID, pPlayer);

    proto_ff::Proto_CSRsp respond;
    *respond.mutable_buy_bag_grid_rsp() = xData.info();
    return NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_BUY_BAG_GRID_RSP, &respond);
}

int NFPackageModule::ProcessStorageItemChange(uint64_t unLinkId, NFDataPackage& packet)
{
    proto_ff::Proto_OnlineToLogicStorageItemChangeNtf ntf;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, ntf);

    uint64_t ullRoleID = packet.nModKey;
    NFPlayer* pPlayer = NFPlayerUtil::GetPlayerByRoleID(ullRoleID);
    CHECK_NULL(ullRoleID, pPlayer);

    proto_ff::Proto_CSRsp respond;
    *respond.mutable_role_item_ntf() = ntf.item_list();
    return NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ACCOUNT_STORAGE_NTF, &respond);
}

int NFPackageModule::ProcessUseItemReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSUseItemReq& oUseItemReq = req.use_item_req();
    uint32_t iItemId = oUseItemReq.item_id();

    auto pItemDesc = ItemDesc::Instance()->GetDesc(iItemId);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pItemDesc, "item_id:{}", iItemId);

    proto_ff::Proto_CSRsp oCSRsp;
    proto_ff::Proto_CSUseItemRsp* pUseItemRsp = oCSRsp.mutable_use_item_rsp();
    pUseItemRsp->set_item_id(iItemId);
    pUseItemRsp->set_result(0);

    int iNum = oUseItemReq.has_num() ? oUseItemReq.num() : 1;
    int iGridIndex = oUseItemReq.grid_index();

    iRetCode = NFServicePackage::CheckUseLimite(pPlayer, iItemId, iNum);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "item use is in limite! itemId:{} iNum:{}", iItemId, iNum);

    CHECK_EXPR(pPlayer->GetLevel() >= pItemDesc->use_min_lv, proto_ff::ERR_CODE_ITEM_USE_FAILED, "player level is not enough!");

    int iPage = oUseItemReq.grid_page();
    if (iPage == 0 && oUseItemReq.grid_index())
    {
        iPage = pItemDesc->bag_page_type;
        CHECK_EXPR(iPage > 0, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item can not be use by grid itemId:{} iNum:{}", iItemId, iNum);
    }

    if (iPage > 0 && iGridIndex >= 0) // 检测过期物品，并且删除
    {
        NFBagPageOpMgr opMgr(pPlayer, proto_ff::EN_ICR_USE_ITEM, true);
        auto pBagOp = opMgr.GetBagPageOpByBagType(iPage);
        CHECK_NULL_WF(pPlayer->GetRoleID(), pBagOp, "page index error:{}", iPage);
        auto pGrid = pBagOp->GetGrid(iGridIndex);
        CHECK_NULL_RET_VAL_WF(pPlayer->GetRoleID(), pGrid, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "grid index error:{}", iGridIndex);
        CHECK_EXPR((uint32_t)iItemId == pGrid->GetItemID(), proto_ff::ERR_CODE_ITEM_USE_FAILED, "error, item id not match, iGridIndex:{} itemId:{} grid itemId:{}", iGridIndex, iItemId, pGrid->GetItemID());
        CHECK_EXPR(oUseItemReq.quality() == pGrid->GetItem().GetQuality(), proto_ff::ERR_CODE_ITEM_USE_FAILED, "error, item id not match, iGridIndex:{} itemId:{} grid itemId:{}", iGridIndex, iItemId, pGrid->GetItemID());
        CHECK_EXPR(pGrid->GetNumber() >= (uint64_t)iNum, proto_ff::ERR_CODE_ITEM_NOT_ENOUGH, "not enough:{} > {}", iNum, pGrid->GetNumber());

        if (pGrid->GetItem().GetEffectTime() > 0 && (pGrid->GetItem().GetEffectTime() <= NF_ADJUST_TIMENOW()))
        {
            iRetCode = pBagOp->DelItemByGrid(iGridIndex);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "page:{} index:{} del item failed", iPage, iGridIndex);
            iRetCode = opMgr.Commit(true);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");

            pUseItemRsp->set_result(proto_ff::ERR_CODE_BAG_ITEM_IS_EXPIRE);
            NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ITEM_USE_RSP, &oCSRsp);

            return proto_ff::ERR_CODE_BAG_ITEM_IS_EXPIRE;
        }
    }

    auto pHandler = NFItemUseFactory::Instance()->GetHandler(pItemDesc->item_type);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pHandler, "item_type:{}", pItemDesc->item_type);

    iRetCode = pHandler(pPlayer, oUseItemReq, pItemDesc, pUseItemRsp, true);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "item_id:{} use failed", iItemId);

    if (pItemDesc->day_use_limite > 0 || pItemDesc->week_use_limite > 0)
    {
        UseItemSuccess(pPlayer, iItemId, iNum, pUseItemRsp->mutable_item_use_limite());
    }
    NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ITEM_USE_RSP, &oCSRsp);
    return 0;
}

int NFPackageModule::UseItemSuccess(NFPlayer* pPlayer, int itemId, int iNum, proto_ff::ItemUseLimite* pUseLimite)
{
    CHECK_NULL(0, pPlayer);
    CHECK_NULL(0, pUseLimite);

    NFServicePackage::OnUse(pPlayer, itemId, iNum);
    return 0;
}

int NFPackageModule::ProcessBoxSelectReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSBoxSelectReq& oReq = req.box_select_req();
    int iPage = oReq.grid_page();
    int iItemId = oReq.item_id();
    int iGridIndex = oReq.grid_index();
    int iSelectIndex = oReq.select_index();
    int iSelectNum = oReq.select_num();

    CHECK_EXPR(iPage > 0 && oReq.grid_index() >= 0 && iPage != 2, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "req error:{}", oReq.DebugString());

    auto pItemDesc = ItemDesc::Instance()->GetDesc(iItemId);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pItemDesc, "item_id:{}", iItemId);

    CHECK_EXPR(pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_BOX && pItemDesc->item_sub_type == proto_ff::EN_SELECTED_BOX, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item can not select:{}", iItemId);
    CHECK_EXPR(iSelectIndex >= 0 && iSelectIndex < (int)pItemDesc->box_select_item.size(), proto_ff::ERR_CODE_INVALID_REQ_PARAM, "select index error:{} >= {}", oReq.select_index(), pItemDesc->box_select_item.size());

    const ItemPair* pSelectItem = &pItemDesc->box_select_item[iSelectIndex];
    CHECK_EXPR(pSelectItem->id > 0 && pSelectItem->num > 0, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "no item:{} {}", iItemId, iSelectIndex);

    proto_ff::Proto_CSRsp oCSRsp;
    proto_ff::Proto_CSBoxSelectRsp* pRsp = oCSRsp.mutable_box_select_rsp();
    pRsp->set_item_id(oReq.item_id());
    pRsp->set_select_index(oReq.select_index());
    pRsp->set_select_num(oReq.select_num());

    iRetCode = NFServicePackage::CheckUseLimite(pPlayer, iItemId, iSelectNum);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "item use is in limite, itemId:{}", iItemId);

    CHECK_EXPR(pPlayer->GetLevel() >= pItemDesc->use_min_lv, proto_ff::ERR_CODE_ITEM_USE_FAILED, "player level is not enough! ");

    NFBagPageOpMgr opMgr(pPlayer, proto_ff::EN_ICR_USE_ITEM, true);
    auto pBagOp = opMgr.GetBagPageOpByBagType(iPage);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pBagOp, "page index error:{}", iPage);
    auto pGrid = pBagOp->GetGrid(iGridIndex);
    CHECK_NULL_RET_VAL_WF(pPlayer->GetRoleID(), pGrid, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "grid index error:{}", iGridIndex);
    CHECK_EXPR((uint32_t)iItemId == pGrid->GetItemID(), proto_ff::ERR_CODE_ITEM_USE_FAILED, "error, item id not match, iGridIndex:{} itemId:{} grid itemId:{}", iGridIndex, iItemId, pGrid->GetItemID());
    CHECK_EXPR(iSelectNum > 0 && pGrid->GetNumber() >= (uint64_t)iSelectNum, proto_ff::ERR_CODE_ITEM_NOT_ENOUGH, "not enough:{} > {}", iSelectNum, pGrid->GetNumber());

    if (pGrid->GetItem().GetEffectTime() > 0 && (pGrid->GetItem().GetEffectTime() <= NF_ADJUST_TIMENOW()))
    {
        opMgr.SetPackageOpReason(EN_ICR_BAG_ITEM_EFFECTIVE_TIME);
        iRetCode = pBagOp->DelItemByGrid(iGridIndex);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "page:{} index:{} del item failed", iPage, iGridIndex);
        iRetCode = opMgr.Commit(true);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");

        pRsp->set_result(proto_ff::ERR_CODE_BAG_ITEM_IS_EXPIRE);
        NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_BOX_SELECT_RSP, &oCSRsp);

        return proto_ff::ERR_CODE_BAG_ITEM_IS_EXPIRE;
    }

    iRetCode = pBagOp->DelItemByGrid(iGridIndex);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "page:{} index:{} del item failed", iPage, iGridIndex);

    iRetCode = opMgr.AddToBag(pSelectItem->id, pSelectItem->num * iSelectNum);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.AddToBag failed, itemID:{} iNum:{}", pSelectItem->id, pSelectItem->num * iSelectNum);

    iRetCode = opMgr.Commit(true);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");

    opMgr.SendRewardNtf(false, proto_ff::EN_REWARD_NOTIFY_TYPE_USE_ITEM, pSelectItem->id);
    opMgr.FillPackageInfoForAdd(pRsp->mutable_items_result());

    if (pItemDesc->day_use_limite > 0 || pItemDesc->week_use_limite > 0)
    {
        UseItemSuccess(pPlayer, iItemId, iSelectNum, pRsp->mutable_item_use_limite());
    }
    NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_BOX_SELECT_RSP, &oCSRsp);
    return 0;
}

int NFPackageModule::ProcessSaveToStorageReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSStorageMoveReq& msg = req.storage_move_pick_req();

    NFTransOpStoreageBag* pTrans = NFTransOpStoreageBag::CreateTrans();
    pTrans->Init(pPlayer, proto_ff::E_CS_STORAGE_SAVE_REQ, packet.nMsgSeq);
    iRetCode = pTrans->ProcessCSMsgReq(&msg);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "ProcessCSMsgReq failed");
    return 0;
}

int NFPackageModule::ProcessPickFromStorageReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSStorageMoveReq& msg = req.storage_move_pick_req();

    if (msg.storage_page() == EN_BPT_TEMP_STORAGE)
    {
        NFBagPageOpMgr opMgr(pPlayer, proto_ff::EN_ICR_PICK_FROM_TEMP_STORAGE);
        opMgr.SetForbidAddWhenFull(true);
        NFBagPageOp* pTempStorageOp = opMgr.GetBagPageOpByBagType(EN_BPT_TEMP_STORAGE);
        CHECK_NULL_WF(pPlayer->GetRoleID(), pTempStorageOp, "GetBagPageOpByBagType EN_BPT_TEMP_STORAGE");

        if (msg.pick_all_items())
        {
            for (int i = 0; i < pTempStorageOp->GetCapacity(); i++)
            {
                auto pGrid = pTempStorageOp->GetGrid(i);
                CHECK_NULL_WF(pPlayer->GetRoleID(), pGrid, "GetGrid index error:{}", i);
                if (pGrid->GetItem().IsEmpty())
                {
                    continue;
                }

                iRetCode = opMgr.AddToBag(pGrid->GetItem(), pGrid->GetNumber());
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "AddToBag item:{}", pGrid->GetItem().ShortDebugString());

                iRetCode = pTempStorageOp->DelItemByGrid(i);
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItemByGrid item:{}", pGrid->GetItem().ShortDebugString());
            }

            iRetCode = opMgr.Commit(true);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");
        }
        else
        {
            auto pGrid = pTempStorageOp->GetGrid(msg.grid_index());
            CHECK_NULL_WF(pPlayer->GetRoleID(), pGrid, "GetGrid index error:{}", msg.grid_index());
            if (pGrid->GetItemID() != msg.item_id() || pGrid->GetUUID() != msg.uuid() || pGrid->GetItem().IsEmpty())
            {
                LOG_ERR(pPlayer->GetRoleID(), -1, "param error:{} {} {} {}", msg.item_id(), msg.uuid(), msg.item_num(), msg.storage_page());
                return proto_ff::ERR_CODE_INVALID_REQ_PARAM;
            }

            iRetCode = opMgr.AddToBag(pGrid->GetItem(), msg.item_num());
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "AddToBag item:{} item_num:{}", pGrid->GetItem().ShortDebugString(), msg.item_num());

            iRetCode = pTempStorageOp->DelItemByGrid(msg.grid_index());
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItemByGrid item:{}", pGrid->GetItem().ShortDebugString());

            iRetCode = opMgr.Commit(true);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "opMgr.Commit failed");
        }

        proto_ff::Proto_CSRsp respond;
        proto_ff::Proto_CSStorageMoveRsp* rsp = respond.mutable_storage_move_pick_resp();
        rsp->set_storage_page(msg.storage_page());

        rsp->set_grid_index(msg.grid_index());
        return NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_STORAGE_PICK_RSP, &respond);
    }
    else if (msg.storage_page() == EN_BPT_STORAGE)
    {
        NFTransOpStoreageBag* pTrans = NFTransOpStoreageBag::CreateTrans();
        pTrans->Init(pPlayer, proto_ff::E_CS_STORAGE_PICK_REQ, packet.nMsgSeq);
        iRetCode = pTrans->ProcessCSMsgReq(&msg);
        CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "ProcessCSMsgReq failed");
    }
    else
    {
        LOG_ERR(pPlayer->GetRoleID(), -1, "storage_page error:{}", msg.storage_page());
        return ERR_CODE_INVALID_REQ_PARAM;
    }

    return 0;
}

int NFPackageModule::ProcessItemExchangeReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    return 0;
}

int NFPackageModule::ProcessThrowawayReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    auto pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    const proto_ff::Proto_CSStorageThrowMsg& throwMsg = req.storage_throwaway_req();

    NFBagPageOpMgr opMgr(pPlayer, proto_ff::EN_ICR_ITEM_THROW_AWAY);
    NFBagPageOp* pBagPageOp = opMgr.GetBagPageOpByBagType(throwMsg.page());
    CHECK_NULL_WF(pPlayer->GetRoleID(), pBagPageOp, "GetBagPageOpByBagType, iBagType:%d", throwMsg.page());

    NFBagPageGrid* pGrid = pBagPageOp->GetGrid(throwMsg.grid_index());
    CHECK_NULL_WF(pPlayer->GetRoleID(), pGrid, "GetGrid, iGridIndex:%d", throwMsg.grid_index());
    CHECK_EXPR(pGrid->GetItemID() == throwMsg.item_id(), proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item_id error:, req itemId:{} grid item id:{}", throwMsg.item_id(), pGrid->GetItemID());
    CHECK_EXPR(pGrid->GetNumber() == throwMsg.item_num(), proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item_num error:, req itemId:{} num:{} grid item num:{}", throwMsg.item_id(), throwMsg.item_num(), pGrid->GetNumber());
    CHECK_EXPR(pGrid->GetUUID() == throwMsg.uuid(), proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item_uuid error:, req itemId:{} num:{} uuid:{} grid item uuid:{}", throwMsg.item_id(), throwMsg.item_num(), throwMsg.uuid(), pGrid->GetUUID());

    int iRetCode = pBagPageOp->DelItemByGrid(throwMsg.grid_index());
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItemByGrid, iGridIndex:{}", throwMsg.grid_index());

    iRetCode = opMgr.Commit(true);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "Commit failed");

    proto_ff::Proto_CSRsp Rsp;
    proto_ff::Proto_CSStorageThrowMsg* prsp = Rsp.mutable_storage_throwaway_rsp();
    prsp->CopyFrom(throwMsg);

    NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_STORAGE_THROWAWAY_RSP, &Rsp);
    return 0;
}

int NFPackageModule::ProcessMoneyExchangeReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    return 0;
}

int NFPackageModule::ProcessDecomposeReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    return 0;
}
